﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports roncliProductions.LibWowArmory.Achievement.Strings
Imports System
Imports System.Collections.ObjectModel
Imports System.Globalization
Imports System.IO
Imports System.Linq
Imports System.Web
Imports System.Xml.Serialization

Namespace roncliProductions.LibWowArmory.Character.Feed

    ''' <summary>
    ''' A class that retrieves a character's feed from the Armory
    ''' </summary>
    ''' <remarks></remarks>
    Public Class CharacterFeed
        Inherits WowArmoryData

        Private cfPage As New Schema.feed
        Private acCategories As New Collection(Of AchievementCategory)

        ''' <summary>
        ''' The realm the character is on
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Realm As String

        ''' <summary>
        ''' The name of the character
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Name As String

        ''' <summary>
        ''' Whether or not to show achievements
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Achievements As Boolean = True

        ''' <summary>
        ''' Whether or not to show achievement criteria
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property AchievementCriteria As Boolean = True

        ''' <summary>
        ''' Whether or not to show boss kills
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property BossKills As Boolean = True

        ''' <summary>
        ''' Whether or not to show loot won
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Loot As Boolean = True

        ''' <summary>
        ''' Whether or not to show respecs
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks>This filter currently returns no results.</remarks>
        Public Property Respecs As Boolean = True

        ''' <summary>
        ''' The achievement categories that can be filtered
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Categories As Collection(Of AchievementCategory)
            Get
                Return acCategories
            End Get
        End Property

        ''' <summary>
        ''' The URL that will be used to retrieve the character's feed from the Armory
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL As String
            Get
                Dim ubURL As New URLQueryStringCollection("http://www.wowarmory.com/character-feed-data.xml")

                ubURL.Add("r", Realm)
                ubURL.Add("n", Name)

                If Not (Achievements And AchievementCriteria And BossKills And Loot And Respecs) Then
                    Dim strFeedFilters As New Collection(Of String)
                    If Achievements Then
                        strFeedFilters.Add("ACHIEVEMENT")
                    End If
                    If AchievementCriteria Then
                        strFeedFilters.Add("CRITERIA")
                    End If
                    If BossKills Then
                        strFeedFilters.Add("BOSSKILL")
                    End If
                    If Loot Then
                        strFeedFilters.Add("LOOT")
                    End If
                    If Respecs Then
                        strFeedFilters.Add("RESPEC")
                    End If
                    If strFeedFilters.Count > 0 Then
                        ubURL.Add("filters", String.Join(",", strFeedFilters.ToArray))
                    End If
                End If

                Dim intFilters As Integer = (From c In Categories Where c.Include = False).Count
                If intFilters > 0 And intFilters < (From c In Categories).Count Then
                    Dim strCategoryFilters As New Collection(Of String)
                    For Each acCategory As AchievementCategory In (From c In Categories Where c.Include = True)
                        strCategoryFilters.Add(acCategory.CategoryID.ToString(CultureInfo.InvariantCulture))
                    Next
                    If strCategoryFilters.Count > 0 Then
                        ubURL.Add("achCategories", String.Join(",", strCategoryFilters.ToArray))
                    End If
                End If

                Return ubURL.ToString
            End Get
        End Property

        ''' <summary>
        ''' Indicates to the inherited class that this request does not require login
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property RequiresLogin As Boolean
            Get
                Return False
            End Get
        End Property

        ''' <summary>
        ''' A constructor to initialize the achievement category filters
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            For Each ciCategory As CategoryInfo In (New AchievementStrings).Categories
                Categories.Add(New AchievementCategory(ciCategory.CategoryID, ciCategory.Name, True))
            Next
        End Sub

        ''' <summary>
        ''' A constructor to initialize the achievement category filters, character name, and realm
        ''' </summary>
        ''' <param name="strName"></param>
        ''' <param name="strRealm"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal strName As String, ByVal strRealm As String)
            Me.New()
            Name = strName
            Realm = strRealm
        End Sub

        ''' <summary>
        ''' Performs the feed lookup on the Armory
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Load()
            Dim strKey As String = String.Format(CultureInfo.InvariantCulture, "LibWowArmory.CharacterFeed.{0}", URL)
            If Cache.Cache(strKey) Is Nothing Then
                MyBase.Retrieve()

                Dim xsSerializer As New XmlSerializer(cfPage.GetType)

                Using srXML As New StringReader(MyBase.Data.Replace("<a ", "&lt;a ").Replace("</a>", "&lt;/a>").Replace("<span ", "&lt;span ").Replace("</span>", "&lt;/span>").Replace("<strong>", "&lt;strong>").Replace("</strong>", "&lt;/strong>"))
                    cfPage = CType(xsSerializer.Deserialize(srXML), Schema.feed)
                End Using

                Cache.Cache.Insert(strKey, cfPage, Nothing, Date.UtcNow.AddMinutes(15), Nothing, Caching.CacheItemPriority.Normal, Nothing)
            Else
                cfPage = CType(Cache.Cache(strKey), Schema.feed)
            End If
        End Sub

        ''' <summary>
        ''' The character feed of the user
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Feed As Collection(Of FeedEvent)
            Get
                If cfPage Is Nothing Then
                    Return New Collection(Of FeedEvent)
                End If
                Return (From fe In cfPage.event Select New FeedEvent(fe.character.First.name, fe.character.First.characterurl, Date.Parse(String.Format(CultureInfo.InvariantCulture, "{0} {1}", fe.date, fe.time), CultureInfo.InvariantCulture), fe.desc, fe.icon, fe.id, fe.points, fe.reldate, CType(fe.slot, Enums.ItemSlotType), GetFeedSortType(fe.sort), fe.title, fe.tooltip, GetFeedEventType(fe.type))).ToCollection
            End Get
        End Property

        Private Shared Function GetFeedSortType(ByVal strSort As String) As Enums.FeedSortType
            Select Case strSort.ToUpperInvariant
                Case "TODAY"
                    Return Enums.FeedSortType.Today
                Case "YESTERDAY"
                    Return Enums.FeedSortType.Yesterday
                Case "EARLIER"
                    Return Enums.FeedSortType.Earlier
                Case Else
                    Return Enums.FeedSortType.Unknown
            End Select
        End Function

        Private Shared Function GetFeedEventType(ByVal strType As String) As Enums.FeedEventType
            Select Case strType.ToUpperInvariant
                Case "ACHIEVEMENT"
                    Return Enums.FeedEventType.Achievement
                Case "CRITERIA"
                    Return Enums.FeedEventType.Criteria
                Case "BOSSKILL"
                    Return Enums.FeedEventType.BossKill
                Case "LOOT"
                    Return Enums.FeedEventType.Loot
                Case "RESPEC"
                    Return Enums.FeedEventType.Respec
                Case Else
                    Return Enums.FeedEventType.Unknown
            End Select
        End Function

    End Class

End Namespace